﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading;
using System.Threading.Tasks;
using XchangeStreamer.Core.Subscriber;

namespace XchangeStreamer.Subscriber.SDK
{
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
    internal sealed class Callback : INotification, IDisposable
    {
        #region Private Fields

        private Dispatcher dispatcher;
        private int disposed = 0;
        private int lastReceivedMessageId = 0;
        private int currentReceivedMessageId = 0;
        private Action<System.ServiceModel.Channels.Message> processMessage;

        #endregion

        #region Const.

        private Callback()
        { }

        public Callback(Action<System.ServiceModel.Channels.Message> processMessage)
        {
            this.dispatcher = new Dispatcher();
            this.processMessage = processMessage;
        }

        #endregion

        #region INotification Members

        [OperationBehavior(AutoDisposeParameters = false)]
        public void Notify(System.ServiceModel.Channels.Message message)
        {
            Task.Factory.StartNew(() =>
            {
                this.currentReceivedMessageId = int.Parse(message.Headers.MessageId.ToString());
                //Console.WriteLine("MessageId: {0}", this.currentReceivedMessageId);
                if (this.currentReceivedMessageId > this.lastReceivedMessageId)
                {
                    this.lastReceivedMessageId = this.currentReceivedMessageId;
                }
                this.processMessage(message);
            },
            CancellationToken.None, TaskCreationOptions.None, this.dispatcher);
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            if (Interlocked.CompareExchange(ref this.disposed, 1, 0) == 0)
            {
                this.dispatcher.Dispose();
                this.dispatcher = null;
            }
        }

        #endregion
    }
}
